package com.cxm.weilai.util;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 日期工具.
 *
 * @author admin.zjs
 */
public class DateUtil {

    private static Log logger = LogFactory.getLog(DateUtil.class);

    public static final String[] WEEK_ENUM = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};

    public static final SimpleDateFormat CHS_DATE = new SimpleDateFormat("yyyy年MM月dd日");
    public static final SimpleDateFormat SIM_DATE = new SimpleDateFormat("yyyy-MM-dd");
    public static final SimpleDateFormat SIM_DATE_MOTH = new SimpleDateFormat("yyyy-MM");
    public static final SimpleDateFormat SIM_TIME = new SimpleDateFormat("HH:mm:ss");
    public static final SimpleDateFormat SIM_DATE_TIME = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static final String allTime = "yyyy-MM-dd HH:mm:ss";
    public static final String allDate = "yyyy-MM-dd";
    public static final String allDateMonth = "yyyy-MM";
    public static final String year = "yyyy";
    private static Date defaultDate = null;

    /**
     * 日期型格式化成字符型
     *
     * @param date
     * @param format
     * @return
     */
    public static String format(Date date, String format) {
        SimpleDateFormat formatter = null;
        if (date == null) {
            return null;
        } else if (StringUtils.isEmpty(format) || format.length() < 5) {
            formatter = new SimpleDateFormat("yyyy-MM-dd");
        } else {
            formatter = new SimpleDateFormat(format);
        }
        return formatter.format(date);
    }

    /**
     * 结构化时间
     *
     * @param dateString
     * @param dateFormat
     * @param targetResultType
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T extends Date> T parse(String dateString,
                                           String dateFormat, Class<T> targetResultType) {
        if (StringUtils.isEmpty(dateString)) {
            return null;
        }
        DateFormat df = new SimpleDateFormat(dateFormat);
        try {
            long time = df.parse(dateString).getTime();
            Date t = targetResultType.getConstructor(long.class).newInstance(
                    time);
            return (T) t;
        } catch (ParseException e) {
            T descDate = (T) parseErrorDate(dateString);
            if (descDate == null) {
                String errorInfo = "cannot use dateformat:" + dateFormat
                        + " parse datestring:" + dateString;
                throw new IllegalArgumentException(errorInfo, e);
            } else {
                return descDate;
            }
        } catch (Exception e) {
            throw new IllegalArgumentException("error targetResultType:"
                    + targetResultType.getName(), e);
        }
    }

    /**
     * 处理时间格式化失败的字符创
     *
     * @param dateString
     * @return
     */
    public static Date parseErrorDate(String dateString) {
        Date descDate = null;
        DateFormat df = null;
        List<String> sdfList = new ArrayList<String>();
        sdfList.add("yyyy-MM-dd");
        sdfList.add("yyyy/MM/dd");
        sdfList.add("yyyy.MM.dd");
        sdfList.add("yy-MM-dd");
        sdfList.add("yy.MM.dd");
        sdfList.add("yyyy-MM-dd hh:mm:ss");
        sdfList.add("yyyy/MM/dd hh:mm:ss");
        for (String sdf : sdfList) {
            if (descDate != null) {
                break;
            } else {
                try {
                    df = new SimpleDateFormat(sdf);
                    descDate = df.parse(dateString);
                } catch (Exception e) {
                    descDate = null;
                }
            }
        }
        return descDate;
    }

    /**
     * 获取当前日期
     */
    public static Date getDefaultDate() {
        if (defaultDate == null) {
            defaultDate = new Date();
        }
        defaultDate.setTime(System.currentTimeMillis());
        return defaultDate;
    }

    /**
     * 字符串转日期.
     *
     * @param str String
     * @return Date
     * @throws ParseException parseException
     */
    public static Date str2Date(String str) throws ParseException {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = new Date();
        date = dateFormat.parse(str);
        return date;
    }

    /**
     * 字符串转日期.
     *
     * @param dateString String
     * @return Date
     */
    public static Date parseDate(String dateString) {
        Date date = null;
        try {
            date = DateUtils.parseDate(dateString, new String[]{"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd"});
        } catch (Exception ex) {
            logger.error("Pase the Date(" + dateString + ") occur errors:" + ex.getMessage());
        }
        return date;
    }

    /**
     * 格式 yyMMdd.
     *
     * @return yyMMdd
     */
    public static String getDate() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
        return sdf.format(new Date());
    }

    /**
     * 2060908 zjs
     * 格式 yyMMdd.
     *
     * @return yyMMdd
     */
    public static String getDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
        return sdf.format(date);
    }

    /**
     * 返回日期
     *
     * @param date 日期 yyyy-mm-dd
     * @return 返回指定月份添加天数后的时间
     */
    public static Date getDate(Date date, int addDay, int addMonth) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, addMonth);
        calendar.add(Calendar.DAY_OF_MONTH, addDay);
        return calendar.getTime();
    }

    /**
     * 格式 yyyyMMdd.
     *
     * @return yyyyMMdd
     */
    public static String getDateDay() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        return sdf.format(new Date());
    }

    /**
     * 格式 yyyyMM.
     *
     * @return yyyyMM
     */
    public static String getDateMonth(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
        return sdf.format(date);
    }

    /**
     * 格式 yyyyMM.
     *
     * @return yyyyMM
     */
    public static String getDateMonthS(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        return sdf.format(date);
    }

    /**
     * 格式 yyyyMMddHHmmSS.
     *
     * @return yyyyMMddHHmmSS
     */
    public static String getDateSecond() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        return sdf.format(new Date());
    }

    /**
     * 格式 yyyy-MM-dd.
     *
     * @return String
     */
    public static String getSIMDate() {
        return SIM_DATE.format(new Date());
    }

    /**
     * 格式 yyyy-MM-dd.
     *
     * @return String
     */
    public static String getSimDate(Date date) {
        return SIM_DATE.format(date);
    }

    /**
     * 格式 yyyy-MM-dd HH:mm:ss.
     *
     * @return yyyy-MM-dd HH:mm:ss
     */
    public static String getDateTime() {
        return SIM_DATE_TIME.format(new Date());
    }

    /**
     * 20160909 zjs 传Date参数
     * 格式 yyyy-MM-dd HH:mm:ss.
     *
     * @return yyyy-MM-dd HH:mm:ss
     */
    public static String getDateTime(Date date) {
        return SIM_DATE_TIME.format(date);
    }

    /**
     * 输出自定义格式的日期字符串.
     *
     * @param formatStr String
     * @return String
     */
    public static String getFormatedDate(String formatStr) {
        SimpleDateFormat sdf = new SimpleDateFormat(formatStr);
        return sdf.format(new Date());
    }

    public static String getTime() {
        return SIM_TIME.format(new Date());
    }

    /**
     * Date转String.
     *
     * @param date Date
     * @return String
     */
    public static String getTime(Date date) {
        if (date == null) {
            return "";
        } else {
            return SIM_TIME.format(date);
        }
    }

    public static String getCHSDate2String() {
        return CHS_DATE.format(new Date());
    }

    /**
     * yyyy年MM月dd日.
     *
     * @param date Date
     * @return String
     */
    public static String getCHSDate2String(Date date) {
        if (date == null) {
            return "";
        } else {
            return CHS_DATE.format(date);
        }
    }

    /**
     * 时间格式.
     *
     * @param date yyyy-MM-dd HH:mm:ss
     * @return String
     */
    public static String getSIMDateTime2String(Date date) {
        if (date == null) {
            return "";
        } else {
            return SIM_DATE_TIME.format(date);
        }
    }

    /**
     * String转Date.
     *
     * @param date String
     * @return Date
     */
    public static Date parseCHSDate(String date) {
        try {
            return CHS_DATE.parse(date);
        } catch (ParseException ex) {
            return null;
        }
    }

    /**
     * String转Date.
     *
     * @param date String
     * @return Date
     */
    public static Date parseDateMOTH(String date) {
        try {
            return SIM_DATE_MOTH.parse(date);
        } catch (ParseException ex) {
            return null;
        }
    }

    /**
     * Long转Date.
     *
     * @param date String
     * @return Date
     */
    public static Date parseSIMDateTime2Date(Long date) {
        try {
            return parseSIMDateTime2Date(SIM_DATE_TIME.format(date));
        } catch (Exception ex) {
            return null;
        }
    }

    /**
     * String转Date.
     *
     * @param date String
     * @return Date
     */
    public static Date parseSIMDateTime2Date(String date) {
        try {
            return SIM_DATE_TIME.parse(date);
        } catch (ParseException ex) {
            return null;
        }
    }

    /**
     * String转Date.
     *
     * @param date String
     * @return Date
     */
    public static Date parseSIMDate2Date(String date) {
        try {
            return SIM_DATE.parse(date);
        } catch (ParseException ex) {
            return null;
        }
    }

    /**
     * Date转String.
     *
     * @param date Date
     * @return String
     */
    public static String getSIMDate2String(Date date) {
        if (date == null) {
            return "";
        } else {
            return SIM_DATE.format(date);
        }
    }

    /**
     * String转Date.
     *
     * @param date String
     * @return Date
     */
    public static Date parseSIMDate(String date) {
        try {
            return SIM_DATE.parse(date);
        } catch (ParseException ex) {
            return null;
        }
    }

    /**
     * 获取当前时间String.
     *
     * @return String
     */
    public static String getLongCHSDate() {
        Calendar now = Calendar.getInstance();
        return getCHSDate2String(now.getTime()) + WEEK_ENUM[now.get(Calendar.DAY_OF_WEEK)];
    }

    /**
     * 获取当前时间String.
     *
     * @param date Date
     * @return String
     */
    public static String getLongCHSDate(Date date) {
        if (date == null) {
            return "";
        } else {
            Calendar now = Calendar.getInstance();
            now.setTime(date);
            return getCHSDate2String(now.getTime()) + WEEK_ENUM[now.get(Calendar.DAY_OF_WEEK)];
        }
    }

    /**
     * 日期差.
     *
     * @param c1 Calendar
     * @param c2 Calendar
     * @return long
     */
    public static long dayDiff(Calendar c1, Calendar c2) {
        long l1 = c1.getTimeInMillis();
        long l2 = c2.getTimeInMillis();
        long diff = l2 - l1;
        long hourDiff = diff % (1000 * 60 * 60 * 24);
        long dayDiff = diff / (1000 * 60 * 60 * 24);
        if (hourDiff > 0) {
            dayDiff++;
        }
        return dayDiff;
    }

    /**
     * 天数差
     *
     * @param start 开始时间（YYYY-MM-dd）
     * @param end   结束时间（YYYY-MM-dd）
     * @return days 天数差
     */
    public static long dayDiff(String start, String end) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date fDate = sdf.parse(start);
        Date oDate = sdf.parse(end);
        long days = (oDate.getTime() - fDate.getTime()) / (1000 * 3600 * 24);
        return days;
    }

    /**
     * 毫秒差.
     *
     * @param c1 Calendar
     * @param c2 Calendar
     * @return long
     */
    public static long milliDiff(Calendar c1, Calendar c2) {
        long l1 = c1.getTimeInMillis();
        long l2 = c2.getTimeInMillis();
        long diff = l2 - l1;
        return diff;
    }

    /**
     * 毫秒差
     */
    public static long milliDiff(Date date1, Date date2) {
        long l1 = date1.getTime();
        long l2 = date2.getTime();
        long diff = l2 - l1;
        return diff;
    }

    /**
     * 判断日期是否在范围内.
     *
     * @param calendar Calendar
     * @param start    Calendar
     * @param end      Calendar
     * @return boolean
     */
    public static boolean calendarBetween(Calendar calendar, Calendar start, Calendar end) {
        if ((calendar == null) || (start == null) || (end == null)) {
            return false;
        }
        if ((calendar.after(start) || calendar.equals(start)) && (calendar.before(end) || calendar.equals(end))) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 设置起始日期.
     *
     * @param cal Calendar
     * @return Calendar
     */
    public static Calendar setStartDay(Calendar cal) {
        cal.set(11, 0);
        cal.set(12, 0);
        cal.set(13, 0);
        return cal;
    }

    /**
     * 设置结束日期.
     *
     * @param cal Calendar
     * @return Calendar
     */
    public static Calendar setEndDay(Calendar cal) {
        cal.set(11, 23);
        cal.set(12, 59);
        cal.set(13, 59);
        return cal;
    }

    /**
     * 复制年月日.
     *
     * @param destCal   Calendar
     * @param sourceCal Calendar
     */
    public static void copyYearMonthDay(Calendar destCal, Calendar sourceCal) {
        destCal.set(1, sourceCal.get(1));
        destCal.set(2, sourceCal.get(2));
        destCal.set(5, sourceCal.get(5));
    }

    /**
     * 时间转12小时制时间.
     *
     * @param date Date
     * @return String
     */
    public static String formatEnDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss a");

        return sdf.format(date).replaceAll("上午", "AM").replaceAll("下午", "PM");
    }

    /**
     * 获取时间对应一年中的周数.
     *
     * @param date     Date
     * @param lastWeek int
     * @return String
     */
    public static String getWeekMember(Date date, int lastWeek) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int num = calendar.get(Calendar.WEEK_OF_YEAR);
        return String.valueOf(num - 1 - lastWeek);
    }

    /**
     * 根据n,将时间转化为之前的月份，如2016-05.
     *
     * @param date      Date
     * @param lastMonth int
     * @return String
     */
    public static String getMonthMember(Date date, int lastMonth) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, -lastMonth);
        date = calendar.getTime();
        return DateUtil.getSIMDate2String(calendar.getTime()).substring(0, 7);
    }

    /**
     * 获取时间对应的月份，如6.
     *
     * @param date      Date
     * @param lastMonth int
     * @return int
     */
    public static int getMonthMemberIndidual(Date date, int lastMonth) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, -lastMonth);
        return calendar.get(Calendar.MONTH) + 1;
    }

    /**
     * 根据n,将时间转化为之前的日期，如2016-06-15.
     *
     * @param date         Date
     * @param lastMonthDay int
     * @return String
     */
    public static String getDayMember(Date date, int lastMonthDay) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, -lastMonthDay);
        date = calendar.getTime();
        return DateUtil.getSIMDate2String(date);
    }

    /**
     * 获取时间对应的年份.
     *
     * @param date           Date
     * @param lastYearMember int
     * @return String
     */
    public static String getYearMember(Date date, int lastYearMember) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.YEAR, -lastYearMember);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        return sdf.format(calendar.getTime());
    }

    /**
     * 获取时间对应的季度数.
     *
     * @param date              Date
     * @param lastQuarterMember int
     * @return String
     */
    public static String getQuarterMember(Date date, int lastQuarterMember) {
        int quarter = 0;
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int month = calendar.get(Calendar.MONTH);
        if ((month >= 1) && (month <= 3)) {
            quarter = 1;
        }
        if ((month >= 4) && (month <= 6)) {
            quarter = 2;
        }
        if ((month >= 7) && (month <= 9)) {
            quarter = 3;
        }
        if ((month >= 10) && (month <= 12)) {
            quarter = 4;
        }
        return String.valueOf(quarter - lastQuarterMember);
    }

    /**
     * 时间进行相加减.
     *
     * @param date Date
     * @return Date
     */
    public static Date dateOperation(Date date, int dateNum) {
        Date dt1 = null;
        if (null != date) {
            Calendar rightNow = Calendar.getInstance();
            rightNow.setTime(date);
            rightNow.add(Calendar.DAY_OF_YEAR, dateNum);// 日期加减天数
            dt1 = rightNow.getTime();
        }
        return dt1;
    }

    /**
     * 转换为时间（天,时:分:秒.毫秒）
     */
    public static String formatDateTime(long timeMillis) {
        long day = timeMillis / (24 * 60 * 60 * 1000);
        long hour = ((timeMillis / (60 * 60 * 1000)) - (day * 24));
        long min = ((timeMillis / (60 * 1000)) - (day * 24 * 60) - (hour * 60));
        long s = ((timeMillis / 1000) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (min * 60));
        long sss =
                (timeMillis - (day * 24 * 60 * 60 * 1000) - (hour * 60 * 60 * 1000) - (min * 60 * 1000) - (s * 1000));
        return (day > 0 ? day + "," : "") + hour + ":" + min + ":" + s + "." + sss;
    }

    /**
     * 返回月份
     *
     * @param date 日期
     * @return 返回月份
     */
    public static int getMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.MONTH) + 1;
    }

    /**
     * 返回日份
     *
     * @param date 日期
     * @return 返回日份
     */
    public static int getDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 返回年月
     *
     * @param date 日期 yyyy-mm
     * @return 返回指定月份添加天数后的时间
     */
    public static Date getDay(Date date, int addDay) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, addDay);
        return calendar.getTime();
    }

    /**
     * 获取过去的小时
     *
     * @param date
     * @return
     */
    public static long pastHour(Date date) {
        long t = new Date().getTime() - date.getTime();
        return t / (60 * 60 * 1000);
    }


}
